#include <linux/init.h>
#include <linux/kallsyms.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>

#define BUFSIZE 1024

static struct proc_dir_entry* proc_test;
static char*                  buf;
static unsigned int           len;

// ES_init_nsproxy = (struct nsproxy *)kallsyms_lookup_name("init_nsproxy");
// 比较ns：if(ES_init_nsproxy != current->nsproxy)printk("%d\n", __LINE__);

static ssize_t mywrite(struct file* file, const char __user* ubuf, size_t count,
                       loff_t* ppos)
{
    if (count <= 0) return -EFAULT;

    len = count > BUFSIZE ? BUFSIZE : count;

    // kfree memory by kmalloc before
    if (buf != NULL) kfree(buf);
    buf = (char*)kmalloc(len + 1, GFP_KERNEL);
    if (buf == NULL) {
        printk("kmalloc failure\n");
        return -EFAULT;
    }

    memset(buf, 0, len + 1);
    if (copy_from_user(buf, ubuf, len)) return -EFAULT;
    printk("writing %d char:%s", len, buf);
    return len;
}

static ssize_t myread(struct file* file, char __user* ubuf, size_t count,
                      loff_t* ppos)
{
    if (*ppos > 0) return 0;

    printk("read = %s", buf);

    if (copy_to_user(ubuf, buf, len)) return -EFAULT;
    *ppos = *ppos + len;
    return len;
}

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .read  = myread,
    .write = mywrite,
};

static int proc_init(void)
{
    proc_test = proc_create("proc_test", 0660, NULL, &fops);
    if (proc_test == NULL) return -ENOMEM;

    printk("proc_test init success!");
    return 0;
}

static void proc_cleanup(void)
{
    proc_remove(proc_test);
    printk("proc_test cleanup");
}

module_init(proc_init);
module_exit(proc_cleanup);
MODULE_LICENSE("GPL");

/*
struct file_operations {
    struct module *owner;
    loff_t (*llseek) (struct file *, loff_t, int);
    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
    ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
    ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
    int (*iterate) (struct file *, struct dir_context *);
    int (*iterate_shared) (struct file *, struct dir_context *);
    unsigned int (*poll) (struct file *, struct poll_table_struct *);
    long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
    long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
    int (*mmap) (struct file *, struct vm_area_struct *);
    int (*open) (struct inode *, struct file *);
    int (*flush) (struct file *, fl_owner_t id);
    int (*release) (struct inode *, struct file *);
    int (*fsync) (struct file *, loff_t, loff_t, int datasync);
    int (*fasync) (int, struct file *, int);
    int (*lock) (struct file *, int, struct file_lock *);
    ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *,
int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned
long, unsigned long, unsigned long); int (*check_flags)(int); int (*flock)
(struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct
pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t
(*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t,
unsigned int); int (*setlease)(struct file *, long, struct file_lock **, void
**); long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len);
    void (*show_fdinfo)(struct seq_file *m, struct file *f);
#ifndef CONFIG_MMU
    unsigned (*mmap_capabilities)(struct file *);
#endif
    ssize_t (*copy_file_range)(struct file *, loff_t, struct file *,
            loff_t, size_t, unsigned int);
    int (*clone_file_range)(struct file *, loff_t, struct file *, loff_t,
            u64);
    ssize_t (*dedupe_file_range)(struct file *, u64, u64, struct file *,
            u64);
};
*/
